package com.zbzly.reactive.reactiverbac.config;

import com.zbzly.reactive.reactiverbac.filter.JwtWebFilter;
import com.zbzly.reactive.reactiverbac.security.JwtSecurityContextRepository;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.authentication.ServerAuthenticationFailureHandler;
import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler;

@Configuration
@EnableReactiveMethodSecurity
@EnableWebFluxSecurity //开启webflux security
public class ReactiveSecurityConfiguration {
    @Resource
    private ServerAuthenticationFailureHandler failureHandler;
    @Resource
    private ServerAuthenticationSuccessHandler successHandler;
    @Resource
    private JwtSecurityContextRepository jwtSecurityContextRepository;
    @Resource
    private JwtWebFilter jwtWebFilter;
    private static final String[] AUTH_WHITELIST = new String[]{"/manage/login", "/login", "/user/login",
            "/actuator/**", "/user/**", "/v3/**", "/webjars/**", "/swagger-resources/**", "/doc.html",
            "swagger-ui.html"};

    @Bean
    public SecurityWebFilterChain manageSecurityFilterChain(ServerHttpSecurity http) {
        http
//                .securityMatcher(ServerWebExchangeMatchers.pathMatchers("/manage/**"))
                .formLogin(formLoginSpec -> formLoginSpec
                        .authenticationSuccessHandler(successHandler)
                        .authenticationFailureHandler(failureHandler))
                .csrf(ServerHttpSecurity.CsrfSpec::disable)
                .httpBasic(ServerHttpSecurity.HttpBasicSpec::disable)
                .securityContextRepository(jwtSecurityContextRepository)
                .addFilterBefore(jwtWebFilter, SecurityWebFiltersOrder.AUTHORIZATION)
                .authorizeExchange(authorizeExchangeSpec -> authorizeExchangeSpec
                        .pathMatchers(AUTH_WHITELIST).permitAll()
                        .pathMatchers("/manage/api/**").hasRole("MANAGE")
                        .anyExchange().authenticated());
        return http.build();
    }

    @Bean
    public PasswordEncoder password() {
        return new BCryptPasswordEncoder();
    }

}
